/**
 * @function datagrid-js
 * @encode utf-8
 * @copyright (C) lijun
 * @file datagrid.js
 * @author lijun
 * @version 1.2
 * @date 2010-7-17
 */

/**
 * 列头属性
 * @param String column 列名
 */
XLib.DataGridColumn = function(column)
{
    this.column = column;
    this.width = 0;
    this.headerText = null;
    this.cssText = null;
    this.className = null;
    this.id = null;
};

/**
 * 数据类
 * @param Array itemList 数据项列表
 */
XLib.DataProvider = function(itemList)
{
    return itemList;
};

XLib.DataGrid = function()
{
    this.cols = 0;
    this.rows = 0;
    this.rowHeight = 22;
    this.cssText = null;
    this.className = null;
    this.id = null;
    this.parent = null;
    this.showHeaders = true;
    this.showPager = false;
    this.resizbleColumns = false;
    this.rowCount = 8;
    this.colCount = 4;
    this.editable = false;
    this.dragable = false;
    this.drag = true;
    this.dataProvider = [];
    this.columns = [];
    this.hiddenCount = 0;
    this.columnSelectorDisplay = false;
    this.columnSelectorArrow = null;
};

XLib.DataGrid.prototype = {
    /**
     * 添加列
     * @param DataGridColumn dataColumn
     */
    addColumn : function(dataColumn)
    {
        this.columns.push(dataColumn);
    },
    /**
     * 在指定的位置添加列
     * @param DataGridColumn dataColumn
     * @param int index
     */
    addColumnAt : function(dataColumn, index)
    {
        var len = this.cols;
        if(index >= len)
        {
            this.addColumn(dataColumn);
        }
        else
        {
            var tmp = this.columns.splice(index, len - index);
            this.columns[index] = dataColumn;
            this.columns.concat(tmp);
        }
    },
    /**
     * 移除指定位置的列
     * @param int index
     */
    removeColunmAt : function(index)
    {
        this.columns.splice(index, 1);
    },
    /**
     * 移除所有列
     */
    removeAllColumns : function()
    {
        this.columns = [];
    },
    /**
     * 添加数据项
     * @param Object item
     */
    addItem : function(item)
    {
        this.dataProvider.push(item);
    },
    /**
     * 在指定的位置添加数据项
     * @param Object item
     * @param int index
     */
    addItemAt : function(item, index)
    {
        var len = this.rows;
        if(index >= len)
        {
            this.addItem(item);
        }
        else
        {
            var tmp = this.dataProvider.splice(index, len - index);
            this.dataProvider[index] = item;
            this.dataProvider.concat(tmp);
        }
    },
    /**
     * 移除指定的列
     * @param Object item
     */
    removeItem : function(item)
    {
        var len = this.rows;
        var data = null;
        for(var i = 0; i < len; i++)
        {
            data = this.dataProvider[i];
            if(item = data)
            {
                this.removeItemAt(i);
                data = null;
                break;
            }
        }
    },
    /**
     * 移除指定位置的列
     * @param int index
     */
    removeItemAt : function(index)
    {
        this.dataProvider.splice(index, 1);
    },
    /**
     * 创建面板
     */
    createPanel : function()
    {
        var div = XLib.DOM.$E(this.id);
        var tmp = null;
        if(null == div)
        {
            div = XLib.DOM.$C("div");
            div.setAttribute("id", this.id);
            if(this.cssText)
            {
                div.style.cssText = this.cssText;
            }
            if(this.className)
            {
                div.className = className;
            }
            XLib.DOM.$A(div, this.parent);

            if(this.colCount < this.cols)
            {
                tmp = XLib.DOM.$C("div");
                tmp.setAttribute("id", this.id + "_column_selector_container");
                tmp.className = "datagrid-column-selector-container";
                XLib.DOM.$A(tmp, div);
                this.hiddenCount = this.cols - this.colCount;
            }
            if(this.showHeaders)
            {
                tmp = XLib.DOM.$C("div");
                tmp.setAttribute("id", this.id + "_header_container");
                tmp.className = "datagrid-header-container";
                XLib.DOM.$A(tmp, div);
                this.createHeader();
            }
            tmp = XLib.DOM.$C("div");
            tmp.setAttribute("id", this.id + "_items_container");
            tmp.className = "datagrid-items-container";
            XLib.DOM.$A(tmp, div);
            this.createDataGrid();
            if(this.showPager)
            {
                tmp = XLib.DOM.$C("div");
                tmp.setAttribute("id", this.id + "_pager_container");
                tmp.className = "datagrid-pager-container";
                XLib.DOM.$A(tmp, div);
                this.createPager();
            }
        }
    },
    /**
     * 创建表头
     */
    createHeader : function()
    {
        var columns = this.columns;
        var len = columns.length;
        var column = null;
        var item = '<th${thid}${cssText}class="${className}"><div${id}${cssText} class="datagrid-header-column${className}">${headerText}${cite}</div></th>';
        var str = '<table class="datagrid-header" cellpadding="0" cellspacing="1" border="0"><tbody><tr>';
        var o = null;
        var container = XLib.DOM.$E(this.id + "_header_container");
        var display = '';
        var cite = '<div class="datagrid-column-selector"><cite></cite></div>';
        var over = '<dl><dt id="overflow_columns_${id}">${status}</dt><dd>${headerText}</dd></dl>';
        var overColumns = [];
        if(this.colCount >= len)
        {
            cite = "";
        }
        for(var i = 0; i < len; i++)
        {
            column = columns[i];
            if(!column.id)
            {
                this.columns[i]["id"] = column.id = this.id + "_column_" + i;
            }
            o = {
                    "id":(column.id||""),
                    "headerText":(column.headerText||column.column),
                    "status":'◆'
                 };
            if(i >= this.colCount)
            {
                display = " display:none;";
                o["status"] = "";
            }
            overColumns.push(over.format(o));
            o = {
                    "id":' id="' + column.id + '"',
                    "thid":' id="th_' + column.id + '"',
                    "cssText":column.cssText ? ' style="' + column.cssText + ' width:' + (isNaN(column.width) ? 'auto;' : column.width + 'px;') + display + '"' : ' style="' + 'width:' + (isNaN(column.width) ? 'auto;' : column.width + 'px;') + display + '"',
                    "className":column.className ? ' ' + column.className : '',
                    "headerText":(column.headerText||column.column),
                    "cite":cite
                };
            str += item.format(o);
        }
        str += '</tr></tbody></table>';
        container.innerHTML = str;
        if(this.dragable)
        {
            this.bindDragable();
        }
        if("" != cite)
        {
            var container = XLib.DOM.$E(this.id + "_column_selector_container");
            container.innerHTML = overColumns.join("");
            this.bindColumnSelector();
            this.bindOverflowColumnsEvent();
        }
    },
    /**
     * 绑定事件
     */
    bindOverflowColumnsEvent : function()
    {
        var columns = this.columns;
        var container = XLib.DOM.$E(this.id + "_column_selector_container");
        var items = XLib.DOM.$T("dl", container);
        var size = items.length;
        var item = null;
        var column = null;
        for(var i = 0; i < size; i++)
        {
            item = items[i];
            column = columns[i];
            XLib.Event.addEventListener(item, "mouseover", function(){this.className = 'datagrid-overflow-items-hover'}, [], false);
            XLib.Event.addEventListener(item, "mouseout", function(){this.className = ''}, [], false);
            XLib.Event.addEventListener(item, "click", this.checkedColumn, [this, column], false);
        }
    },
    /**
     * 选择列
     */
    checkedColumn : function(grid, column)
    {
        var dt = XLib.DOM.$T("dt", this)[0];
        var status = "◆";
        var current = dt.innerHTML;
        var flag = grid.hiddenCount;
        if(grid.hiddenCount < grid.cols - 1)
        {
            if(current == status)
            {
                grid.hiddenCount += 1;
                dt.innerHTML = "";
                grid.setColumnStatus(column, false);
            }
            else
            {
                grid.hiddenCount -= 1;
                dt.innerHTML = status;
                grid.setColumnStatus(column, true);
            }
        }
        else
        {
            if(current != status)
            {
                grid.hiddenCount -= 1;
                dt.innerHTML = status;
                grid.setColumnStatus(column, true);
            }
        }
    },
    /**
     * 获取真实cellIndex
     * 兼容ie6和ie7中cellIndex不正确的问题
     */
    getCellIndex : function(cell, id)
    {
        var isLower = (UA.Browser.ie != -1 && UA.Browser.ie < 8);
        if(isLower)
        {
            var p = cell.parentNode;
            var cells = XLib.DOM.$T(cell.tagName, p);
            var size = cells.length;
            for(var i = 0; i < size; i++)
            {
                if(cells[i].id == id)
                {
                    return i;
                }
            }
        }
        return cell.cellIndex;
    },
    /**
     * 设置列的状态
     */
    setColumnStatus : function(column, isShow)
    {
        var headCell = XLib.DOM.$E(column.id);
        var th = XLib.DOM.$E("th_" + column.id);
        var index = this.getCellIndex(th, "th_" + column.id);
        var items = XLib.DOM.$E(this.id + "_items_container");
        var itemsGrid = XLib.DOM.$T("table", items)[0];
        var itemsRows = itemsGrid.rows;
        var rowSize = itemsRows.length;
        var itemsCells = [];
        var cellSize = 0;
        var display = isShow ? "" : "none";

        th.style.display = display;
        headCell.style.display = display;

        for(var i = 0; i < rowSize; i++)
        {
            itemsCells = itemsRows[i].cells;
            itemsCells[index].style.display = display;
        }
        this.hiddenColumnSelector(this);
    },
    /**
     * 绑定列选择器事件
     */
    bindColumnSelector : function()
    {
        var header = XLib.DOM.$E(this.id + "_header_container");
        var cells = XLib.DOM.getElementsByClassName("datagrid-header-column", header, false);
        var len = cells.length;
        var arrows = [];
        var arrow = null;
        for(var i = 0; i < len; i++)
        {
            arrows = XLib.DOM.getElementsByClassName("datagrid-column-selector", cells[i], true);
            arrow = arrows.length > 0 ? arrows[0] : null;
            if(null == arrow)
            {
                continue;
            }
            XLib.Event.addEventListener(cells[i], "mouseover", this.showColumnSelectorArrow, [this, arrow, "block"], false);
            XLib.Event.addEventListener(cells[i], "mouseout", this.showColumnSelectorArrow, [this, arrow, "none"], false);
            XLib.Event.addEventListener(arrow, "click", this.showColumnSelector, [this], false);
            XLib.Event.addEventListener(arrow, "mousedown", this.stopPropagation, [this], false);
        }
    },
    showColumnSelectorArrow : function(grid, arrow, display)
    {
        if(true == grid.columnSelectorDisplay)
        {
            display = "block";
        }
        arrow.style.display = display;
    },
    /**
     * 阻止事件冒泡
     */
    stopPropagation : function()
    {
        XLib.Event.preventDefault();
        XLib.Event.stopPropagation();
    },
    /**
     * 显示列选择器
     */
    showColumnSelector : function(grid, arrow)
    {
        var container = XLib.DOM.$E(grid.id + "_column_selector_container");
        var pos = XLib.getPosition(this);
        var offset = this.parentNode.offsetHeight;
        this.style.display = "block";
        grid.columnSelectorArrow = this;
        grid.columnSelectorDisplay = true;
        container.style.left = pos.x + "px";
        container.style.top = (offset + pos.y) + "px";
        container.style.display = "block";
        XLib.Event.addEventListener(document, "mouseup", grid.hiddenColumnSelector, [grid], false);
        XLib.Event.addEventListener(container, "mouseup", grid.stopPropagation, [this], false);
    },
    /**
     * 隐藏列选择器
     */
    hiddenColumnSelector : function(grid)
    {
        var container = XLib.DOM.$E(grid.id + "_column_selector_container");
        container.style.display = "none";
        if(grid.columnSelectorArrow)
        {
            grid.columnSelectorArrow.style.display = "none";
            grid.columnSelectorArrow = null;
        }
        grid.columnSelectorDisplay = false;
        XLib.Event.removeEventListener(document, "mouseup", grid.hiddenColumnSelector, [grid], false);
    },
    /**
     * 绑定拖动
     */
    bindDragable : function()
    {
        var header = XLib.DOM.$E(this.id + "_header_container");
        var table = XLib.DOM.$T("table", header)[0];
        var rows = table.rows;
        var cells = rows[0].cells;
        var size = cells.length;
        for(var i = 0; i < size; i++)
        {
            cells[i].style.cursor = "default";
            XLib.Event.addEventListener(cells[i], "mousedown", this.selectColumn, [this, this.columns[i]], false);
        }
    },
    /**
     * 选择列
     */
    selectColumn : function(grid, column)
    {
        var index = grid.getCellIndex(this, this.id);
        var header = XLib.DOM.$E(grid.id + "_header_container");
        var headerGrid = XLib.DOM.$T("table", header)[0];
        var headerRows = headerGrid.rows;
        var headerCells = headerRows[0].cells;

        var items = XLib.DOM.$E(grid.id + "_items_container");
        var itemsGrid = XLib.DOM.$T("table", items)[0];
        var itemsRows = itemsGrid.rows;
        var rowSize = itemsRows.length;
        var itemsCells = [];
        var cellSize = 0;

        var data = [headerCells[index].innerHTML];
        /*
        for(var i = 0; i < rowSize; i++)
        {
            itemsCells = itemsRows[i].cells;
            data.push(itemsCells[index].innerHTML);
        }
        */

        var tmpContainer = XLib.DOM.$E(grid.id + "_tmp_container");
        var str = '<table><tbody>';
        for(var i = 0; i < data.length; i++)
        {
            if(0 == i)
            {
                str += '<tr><th style="width:'+(isNaN(column.width) ? 'auto' : column.width + 'px')+';height:'+(isNaN(grid.rowHeight) ? 'auto' : grid.rowHeight + 'px')+'">'+data[i]+'</th></tr>';
            }
            else
            {
                str += '<tr><td style="width:'+(isNaN(column.width) ? 'auto' : column.width + 'px')+';height:'+(isNaN(grid.rowHeight) ? 'auto' : grid.rowHeight + 'px')+'">'+data[i]+'</td></tr>';
            }
        }
        str += '</tbody></table>';
        if(null == tmpContainer)
        {
            tmpContainer = XLib.DOM.$C("div");
            tmpContainer.setAttribute("id", grid.id + "_tmp_container");
            tmpContainer.style.cssText = 'border:1px dashed #999; background:#ffffee; filter:Alpha(opacity=85); -moz-opacity:0.85; opacity:0.85; position:absolute; display:none;';
            XLib.DOM.$A(tmpContainer);
        }
        tmpContainer.innerHTML = str;
        tmpContainer.style.width = (isNaN(column.width) ? '80px' : column.width + 'px');
        tmpContainer.style.left = (XLib.Event.getClientX() + 5)+'px';
        tmpContainer.style.top = (XLib.Event.getClientY() + 5)+'px';
        tmpContainer.style.display = "block";

        grid.drag = true;
        XLib.Event.removeEventListener(document, "mousemove", grid.moveTo, [this, tmpContainer, grid, column, index], false);
        XLib.Event.removeEventListener(document, "mouseup", grid.insertColumnAt, [this, tmpContainer, grid, column, index], false);
        XLib.Event.addEventListener(document, "mousemove", grid.moveTo, [this, tmpContainer, grid, column, index], false);
        XLib.Event.addEventListener(document, "mouseup", grid.insertColumnAt, [this, tmpContainer, grid, column, index], false);
    },
    /**
     * 移动列
     * @param Node cell
     * @param Node tmpContainer
     * @param DataGrid grid
     * @param DataGridColumn column
     * @param int index
     */
    moveTo : function(cell, tmpContainer, grid, column, index)
    {
        XLib.Event.clearSelection();
        if(grid.drag)
        {
            tmpContainer.style.left = (XLib.Event.getClientX() + 5)+'px';
            tmpContainer.style.top = (XLib.Event.getClientY() + 5)+'px';
        }
    },
    /**
     * 将列插入停止位置
     * @param Node cell
     * @param Node tmpContainer
     * @param DataGrid grid
     * @param DataGridColumn column
     * @param int index
     */
    insertColumnAt : function(cell, tmpContainer, grid, column, index)
    {
        grid.drag = false;
        XLib.Event.removeEventListener(document, "mousemove", grid.moveTo, [cell, tmpContainer, grid, column, index], false);
        XLib.Event.removeEventListener(document, "mouseup", grid.insertColumnAt, [cell, tmpContainer, grid, column, index], false);

        var target = XLib.Event.getSrcElement();
        var targetIndex = grid.getTargetIndex(target, grid);
        if(-1 != targetIndex && targetIndex != index)
        {
            var header = XLib.DOM.$E(grid.id + "_header_container");
            var headerGrid = XLib.DOM.$T("table", header)[0];
            var headerRows = headerGrid.rows;
            var headerCells = headerRows[0].cells;
            var headerCell = headerCells[index];

            var items = XLib.DOM.$E(grid.id + "_items_container");
            var itemsGrid = XLib.DOM.$T("table", items)[0];
            var itemsRows = itemsGrid.rows;
            var rowSize = itemsRows.length;
            var itemsCells = [];
            var itemsCell = null;

            if(targetIndex < index)
            {
                XLib.DOM.$I(headerCell, headerCells[targetIndex]);

                for(var i = 0; i < rowSize; i++)
                {
                    itemsCells = itemsRows[i].cells;
                    itemsCell = itemsCells[index];
                    XLib.DOM.$I(itemsCell, itemsCells[targetIndex]);
                }
            }
            else
            {
                XLib.DOM.$IA(headerCell, headerCells[targetIndex]);

                for(var i = 0; i < rowSize; i++)
                {
                    itemsCells = itemsRows[i].cells;
                    itemsCell = itemsCells[index];
                    XLib.DOM.$IA(itemsCell, itemsCells[targetIndex]);
                }
            }
        }
        tmpContainer.innerHTML = "";
        tmpContainer.style.display = "none";
    },
    /**
     * 获取目标索引
     * @param Node target
     * @param DataGrid grid
     * @param int index
     */
    getTargetIndex : function(target, grid)
    {
        var tag = (target.tagName).toLowerCase();
        var headerId = grid.id + "_header_container";
        var itemsId = grid.id + "_items_container";
        var pNode = target.parentNode;
        if("body" == tag || "html" == tag)
        {
            return -1;
        }
        if("td" == tag || "th" == tag)
        {
            var table = target.parentNode.parentNode.parentNode;
            var container = table.parentNode;
            if(null  == container)
            {
                return  -1;
            }
            else
            {
                if(container.id != headerId && container.id != itemsId)
                {
                    return -1;
                }
            }
            return grid.getCellIndex(target, target.id);
        }
        if(null == pNode)
        {
            return -1;
        }
        return this.getTargetIndex(pNode, grid);
    },
    /**
     * 创建数据项
     */
    createDataGrid : function()
    {
        var columns = this.columns;
        var column = null;
        var items = this.dataProvider;
        var len = items.length;
        var item = null;
        var data = '<td${id} style="width:${width};height:${height};display:${display}">${data}</td>';
        var str = '<table class="datagrid-items" cellpadding="0" cellspacing="1" border="0"><tbody>';
        var o = null;
        var container = XLib.DOM.$E(this.id + "_items_container");
        var index = 0;
        for(var i = 0; i < len; i++)
        {
            item = items[i];
            index = 0;
            str += '<tr>';
            for(var key in item)
            {
                if(item.hasOwnProperty(key))
                {
                    column = columns[index];
                    o = {
                            "id":' id="grid_' + this.id + '_'+ i +'_' + index + '"',
                            "width":(isNaN(column.width) ? 'auto' : column.width + 'px'),
                            "height":(isNaN(this.rowHeight) ? 'auto' : this.rowHeight + 'px'),
                            "data":item[key]
                        };
                    if(index < this.colCount)
                    {
                        o["display"] = "";
                    }
                    else
                    {
                        o["display"] = "none";
                    }
                    str += data.format(o);
                    index++;
                }
            }
            str += '</tr>';
        }
        str += '</tbody></table>';
        container.innerHTML = str;
    },
    /**
     * 创键分页栏
     */
    createPager : function()
    {
    },
    /**
     * 绘制DataGrid
     * @param String id
     * @param String parentId
     */
    drawDataGrid : function(id, parentId)
    {
        this.id = id || "xlib_datagrid";
        this.parent = XLib.DOM.$E(parentId || document.body);
        this.cols = this.columns.length;
        this.rows = this.dataProvider.length;
        this.createPanel();
    }
};